<?php
/**
 * ImagesHelper.php class file.
 * @author wudg <544038230@qq.com>
 * @date 2020/10/29- 5:03 下午
 */

namespace common\helpers;


use Imagine\Image\ManipulatorInterface;
use yii\helpers\FileHelper;
use Yii;
use yii\imagine\Image;

class ImagesHelper
{


    /**
     * 获取随机user-agent
     * @return mixed
     */
    public static function getRandUserAgent()
    {
        $userAgent = [
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
            'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)',
            'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER',
            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;Media Center PC 6.0; .NET4.0C; .NET4.0E)',
            'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)',
            'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)',
            'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;Media Center PC 6.0; .NET4.0C; .NET4.0E)',
            'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1',
            'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;Media Center PC 6.0; .NET4.0C; .NET4.0E)',
            'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;Media Center PC 6.0; .NET4.0C; .NET4.0E)',
            'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
            'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)',
            'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:16.0) Gecko/20121026 Firefox/16.0',
            'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre',
            'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0',
            'Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15',
            'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
            'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
            'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)',
            'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)',
            'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
            'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'
        ];
        return $userAgent[array_rand($userAgent)];

    }

    /**
     * 通过url地址下载图片,返回绝对路径
     * @param string $url
     * @param string $name
     * @param string $timeout
     * @return array|bool
     * @since 判断下附件是否存在，存在直接返回本地地址即可
     */
    public static function downloadByUrl(string $url = '', $timeout = 30)
    {
        try {
            if (!strlen(trim($url))) return false;
            $downloadImageInfo = self::getImageExtname($url);
            $name = $downloadImageInfo['file_name'];
            if (!strlen(trim($name))) return false;
            if(!in_array($downloadImageInfo['ext_name'],Yii::$app->params['pddImageExt'])) return false;
            $date_dir = date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d').DIRECTORY_SEPARATOR.date('H');
            $path = Yii::getAlias('@runtime/upload/'.$date_dir);
            if(!file_exists($path.DIRECTORY_SEPARATOR.$name))
            {
                //目录如果不存就先创建目录
                if(!is_dir($path)) {
                    FileHelper::createDirectory($path);
                }
                $cp = curl_init($url);
                $fp = fopen($path.DIRECTORY_SEPARATOR.$name,"w");
                curl_setopt($cp, CURLOPT_FILE, $fp);
                curl_setopt($cp, CURLOPT_HEADER, 0);
                curl_exec($cp);
                curl_close($cp);
            }

            return [$path.DIRECTORY_SEPARATOR.$name,$name];
        }catch (\Exception $e)
        {
            return false;
        }

    }


    /**
     * 图片二进制保存本地路径
     * @param string $bold
     * @param string $name
     * @return array
     * @since 如果文件存在则不需要再次保存，直接返回即可
     * @throws \yii\base\Exception
     */
    public static function saveBoldToPath(string $bold,string $name)
    {
        $date_dir = date('Y') . DIRECTORY_SEPARATOR . date('m') . DIRECTORY_SEPARATOR . date('d');
        $path = Yii::getAlias('@runtime/upload/'.$date_dir);

        if(!file_exists($path.DIRECTORY_SEPARATOR.$name))
        {
            //目录如果不存就先创建目录
            if(!is_dir($path)) {
                FileHelper::createDirectory($path);
            }
            $fp = fopen($path.DIRECTORY_SEPARATOR.$name,"w");
            fwrite ($fp,$bold);
            fclose ($fp);
        }


        return [$path.DIRECTORY_SEPARATOR.$name,$name];
    }

    /**
     * 获取即将要下载的图片扩展名
     * @param string $url
     * @param string $ex
     * @return array
     */
    public static function getImageExtname($url = '', $ex = 'png')
    {
        $_empty = ['file_name' => '', 'ext_name' => $ex];
        if (!$url) return $_empty;
        if (strpos($url, '?')) {
            $_tarr = explode('?', $url);
            $url = trim($_tarr[0]);
        }
        $arr = explode('.', $url);
        if (!is_array($arr) || count($arr) <= 1) return $_empty;
        $ext_name = trim($arr[count($arr) - 1]);
        if(strlen($ext_name) > 5) $ext_name = null;
        $ext_name = !$ext_name ? $ex : $ext_name;
        return ['file_name' => md5($url) . '.' . $ext_name, 'ext_name' => $ext_name];
    }


    /**
     * 字节转换成M
     * @param int $size
     * @return float
     */
    public static function sizeToM(int $size)
    {
        return (float)sprintf('%.1f',round($size / 1048576 * 100) / 100);
    }

    /**
     * 获取淘宝相对路径图片地址
     * @param string $imgPath
     * @return string|string[]
     */
    public static function getRelationTaobaoImg(string $imgPath)
    {
        return str_replace('https://img.alicdn.com/imgextra/','',$imgPath);
    }


    /**
     * 按高度裁剪图片为多张图
     * @param string $localPath
     * @param int $cutH
     * @return array
     */
    public static function cutImagesByHeight(string $localPath,int $cutH)
    {
        $basePath = pathinfo($localPath,PATHINFO_DIRNAME).DIRECTORY_SEPARATOR;
        $name = basename($localPath);
        list($width, $height) = @getimagesize($localPath);
        $imgList = [];
        if($height > $cutH)
        {
            $num = ceil($height/$cutH);
            for($i=0;$i<$num;$i++)
            {
                $optionY = $cutH*$i;
                $lessH = $height - $optionY;
                if($lessH < $cutH)
                {
                    $cutH = $lessH;
                }
                Image::crop($localPath, $width, $cutH,[0,$optionY])
                    ->save($basePath.$i.'_cut_'.$name);
                $path = $basePath.$i.'_cut_'.$name;
                array_push($imgList,$path);
            }
        }
        return $imgList;
    }


    /**
     * 图片转base64
     * @param $image_file
     * @return string
     */
    public static function base64EncodeImage($image_file)
    {
        $image_info = @getimagesize($image_file);
        if($image_file){
            if(substr($image_file,0,2) == '//'){
                $image_file = 'https:'.$image_file;
            }
            $image_data = file_get_contents($image_file);
            return 'data:' . $image_info['mime'] . ';base64,' . base64_encode($image_data);
        }else{
            return '';
        }

    }


    /**
     * 图片转二进制流
     * @param string $image_file
     * @return bool|string
     */
    public static function fileToBold(string $image_file)
    {
        $fp    = fopen($image_file, 'rb');
        if(!$fp)
        {
            return false;
        }
        $image = addslashes(fread($fp,filesize($image_file)));
        return $image;
    }


    /**
     * 获取正文中的所有图片地址
     * @param string $str
     * @return array|mixed
     */
    public static function getStrImagesList(string $str)
    {
        $content = stripslashes ($str);
        preg_match_all ( '/<img.*?src=[\"|\']?(.*?)[\"|\']?\s.*?>/i',$content, $img_array);

        if(isset($img_array[1]) && count($img_array[1]))
        {
            return $img_array[1];
        }
        return [];

    }


    /**
     * 图片缩略
     * @param string $path
     * @param string $name
     * @param int $width
     * @param int $height
     * @param int $quality
     * @return string
     */
    public static function thumbImg(string $path,string $name,int $width,int $height,int $quality = null)
    {
        $basePath = pathinfo($path,PATHINFO_DIRNAME).DIRECTORY_SEPARATOR;

        $setting = [];
        if($quality)
        {
            $setting['quality'] = $quality;
        }
        Image::thumbnail($path,$width,$height,ManipulatorInterface::THUMBNAIL_OUTBOUND)
            ->save($basePath.'thumb_'.$name,$setting);
        $path = $basePath.'thumb_'.$name;
        return $path;
    }


    /**
     * 添加图片水印
     * @param string $path
     * @param string $name
     * @param string $water_path
     * @param int $position

     * @return string
     */
    public static function watermarkImg(string $path,string $name,string $water_path,int $position = 3)
    {
        list($width, $height) = @getimagesize($path);
        $basePath = pathinfo($path,PATHINFO_DIRNAME).DIRECTORY_SEPARATOR;
        list($water_width, $water_height) = @getimagesize($water_path);

        /**
         * 保证width 和 height 必须存在
         */
        if(!$width || !$height)
        {
            return false;
        }
        list($positionTop,$positionLeft) = self::calWaterImgPosition((int)$width,(int)$height,(int)$water_width,(int)$water_height,$position);

        if($positionTop < 0 || $positionLeft < 0)
        {
            return false;
        }
        Image::watermark($path, $water_path, [$positionTop,$positionLeft])
            ->save($basePath.'img_water_'.$name);

        return $basePath.'img_water_'.$name;
    }

    /**
     * 文字水印
     * @param string $path
     * @param string $name
     * @param string $water_txt
     * @param string $font_file
     * @param array $font_option
     * @param int $position
     * @return string
     */
    public static function watermarkText(string $path,string $name,string $water_txt,string $font_file,array $font_option,int $position = 3)
    {

        list($width, $height) = @getimagesize($path);
        $basePath = pathinfo($path,PATHINFO_DIRNAME).DIRECTORY_SEPARATOR;

        $font_size = intval($font_option['size']) > 0 ? intval($font_option['size']) : 14;


        $font_option['angle'] = ($font_option['angle'] >= 0 && $font_option['angle'] <= 90 || $font_option['angle'] <0 && $font_option['angle'] >= -90) ? $font_option['angle'] : 0;

        $text_size = imagettfbbox($font_size, 0, $font_file, $water_txt);
        if(!$text_size)
        {
            return false;
        }
        $text_width = abs($text_size[0]) + abs($text_size[2]); //文字的最大宽度
        $text_height = abs($text_size[5]) + abs($text_size[1]); //文字的高度

        if ($text_width + 40 > $width || $text_height + 40 > $height) {
            return false;
        }
        list($positionLeft,$positionTop) = self::calWaterTxtPosition((int)$width,(int)$height,(int)$text_width,(int)$text_height,$font_option['angle'],$position);
        if($positionLeft < 0 || $positionTop < 0)
        {
            return false;
        }
        Image::text($path, $water_txt, $font_file,[$positionLeft,$positionTop],$font_option)
            ->save($basePath.'img_txt_'.$name);
        return $basePath.'img_txt_'.$name;
    }


    /**
     * 计算文字水印坐标
     * @param int $width
     * @param int $height
     * @param $text_width
     * @param int $text_height
     * @param int $angle
     * @param int $position
     * @return array
     */
    private static function calWaterTxtPosition(int $width,int $height,$text_width,int $text_height,int $angle,int $position)
    {

//        var_dump('位置：'.$position);
        list($positionX,$positionY) = self::calWaterImgPosition($width,$height,$text_width,$text_height,$position);

//        var_dump('宽高：'.$text_width.'---'.$text_height);
        /**
         * 重新计算倾斜角度的图片占用区域
         */


        //如果有angle旋转角度，则重新设置 top ,left 坐标值
        if ($angle != 0) {
            if ($angle < 90 && $angle > 0) { //顺时针
                $diffTop = ceil(sin(deg2rad($angle)) * $text_width);

                if (in_array($position, array(7, 8, 9))) {// 下步 top 值增加
                    $positionY -= $diffTop;
                } elseif (in_array($position, array(4, 5, 6))) {// 中部 top 值根据图片总高判断
                    if ($text_width > ceil($height / 2)) {
                        $positionY += ceil(($text_width - $height / 2) / 2);
                    }
                }
            } elseif ($angle < 0 && $angle >= -90) {
//                $diffTop = ceil(sin(deg2rad(180 - $angle)) * $text_width);


//                var_dump('差值1：'.$diffTop);
                $angle = abs($angle);
                $new_width = ceil(cos(deg2rad($angle))*$text_width + sin(deg2rad($angle))/$text_height);

                $new_height = ceil(sin(deg2rad($angle))*$text_width + cos(deg2rad($angle))*$text_height);

//                var_dump('sin '.$angle.'= '.sin(deg2rad($angle)));
//                var_dump('cos '.$angle.'=  '.cos(deg2rad($angle)));
//
//                var_dump('新宽高：'.$new_width.'---'.$new_height);

                $diffTop = $new_height - $text_height;
                $diffLeft = abs($new_width-$text_width);
                $positionX += $diffLeft;
//                var_dump('差值2：'.$diffTop.'--'.$diffLeft);
                if (in_array($position, array(0,1, 2, 3))) {// 上部 top 值增加
                    $positionY += $diffTop;

                } elseif (in_array($position, array(4, 5, 6))) {// 中部 top 值根据图片总高判断
                    if ($text_width > ceil($height / 2)) {
                        $positionY = ceil(($height - $diffTop) / 2);
                    }
                }
            }
        }
//        var_dump('位置信息：X:'.$positionX.'----Y:'.$positionY); exit;
        return [$positionX,$positionY];
    }


    /**
     * 计算图片水印位置
     * @param int $width
     * @param int $height
     * @param int $water_width
     * @param int $water_height
     * @param int $position
     * @return array
     */
    private static function calWaterImgPosition(int $width,int $height,int $water_width,int $water_height,int $position)
    {
        switch ($position)
        {
            case 1: //左上角
                $positionX = 10;
                $positionY = 10;
                break;
            case 2: //上中部
                $positionX = ceil($width/2)-ceil($water_width/2);
                $positionY = 0;
                break;
            case 3: //右上角
                $positionX = $width-$water_width;
                $positionY = 10;
                break;
            case 4: //左中
                $positionX = 0;
                $positionY = ceil($height/2)-ceil($water_height/2);
                break;
            case 5: //中间
                $positionX = ceil($width/2)-ceil($water_width/2);
                $positionY = ceil($height/2)-ceil($water_height/2);
                break;
            case 6: //右中
                $positionX = $width - $water_width - 10;
                $positionY = floor(($height - $water_height) / 2);
                break;
            case 7://左下角
                $positionX = 0;
                $positionY = $height-$water_height;
                break;
            case 8: //中下
                $positionX = ceil($width/2)-ceil($water_width/2);
                $positionY = $height-$water_height;
                break;
            case 9://右下角
                $positionX = $width-$water_width;
                $positionY = $height-$water_height;
                break;
            default: //默认左上角
                $positionX = 10;
                $positionY = 10;
                break;
        }
        return [$positionX,$positionY];
    }
}
